import java.util.Vector;

public class StaticPath {

	/**
	 * container for the current path;
	 */
	Vector<IndexNode> path;
	/**
	 * methods which have been called
	 */
	Vector<String> called;
	/**
	 * the index of the cursor
	 */
	int cursor;
	/**
	 * used to record the nodes which have been visited
	 */
	StringBuffer sb;

	public StaticPath() {
		path = new Vector<IndexNode>();
		called = new Vector<String>();
		cursor = -1;
		sb = new StringBuffer();
	}

	/**
	 * add one node at the end of the path
	 * 
	 * @param node
	 */
	public void add(IndexNode node) {
		path.add(node);
	}

	/**
	 * mark the method call which has been invoked
	 * 
	 * @param call
	 */
	public void addCalled(String call) {
		this.called.add(call);
	}

	/**
	 * check if the method has been called before
	 * 
	 * @param call
	 * @return if the method has been called before
	 */
	public boolean isCalled(String call) {
		return called.contains(call);
	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < path.size(); i++) {
			sb.append(path.get(i) + "\n");
		}
		sb.append("\n");
		return sb.toString();
	}

	@Override
	public StaticPath clone() {
		StaticPath spath = new StaticPath();
		spath.setPath(this.path);
		spath.setCalled(this.called);
		spath.setCursor(this.cursor);
		spath.setStringBuffer(this.sb.toString());
		return spath;
	}

	/**
	 * set the previous trace from an existing path
	 * 
	 * @param string
	 */
	private void setStringBuffer(String string) {
		this.sb.append(string);
	}

	/**
	 * set the called trace from an existing path
	 * 
	 * @param called2
	 */
	private void setCalled(Vector<String> called2) {
		for (int i = 0; i < called2.size(); i++) {
			called.add(called2.get(i));
		}
	}

	/**
	 * copy the path trace from an existing path
	 * 
	 * @param path2
	 */
	private void setPath(Vector<IndexNode> path2) {
		for (int i = 0; i < path2.size(); i++) {
			path.add(path2.get(i));
		}
	}

	/**
	 * move the cursor on
	 */
	public void next() {
		this.cursor++;
	}

	/**
	 * get the cursor value
	 * 
	 * @return the cursor value
	 */
	public int getCursor() {
		return this.cursor;
	}

	/**
	 * return how many nodes are in the path
	 * 
	 * @return how many nodes are in the path
	 */
	public int size() {
		return path.size();
	}

	/**
	 * set the cursor value
	 * 
	 * @param i
	 */
	public void setCursor(int i) {
		this.cursor = i;
	}

	/**
	 * get the specific node
	 * 
	 * @param i
	 * @return the specific node
	 */
	public IndexNode getNode(int i) {
		return path.get(i);
	}

	/**
	 * inset the a subpath in a specific position
	 * 
	 * @param ipath
	 * @param j
	 */
	public void insertPath(IndexPath ipath, int j) {
		for (int i = 0; i < ipath.size(); i++) {
			this.path.insertElementAt(ipath.getNode(i), i + j);
		}
	}

	/**
	 * get the current trace of visited node.
	 * 
	 * @return the current trace of visited node.
	 */
	public String getCurrentTrace() {
		return sb.toString() + "\n";
	}

	/**
	 * just record the node at specific position
	 * 
	 * @param i
	 *            the specific position
	 */
	public void recordNode(int i) {
		if (path.get(i).getShouldRecord()) {
			sb.append(path.get(i).getValue() + "\n");
		}
	}

	public boolean contains(String start) {
		for (int i = 0; i < path.size(); i++) {
			if (path.get(i).getValue().equals(start)) {
				return true;
			}
		}
		return false;
	}

}
